package xcmg.device.util;

import org.apache.commons.lang3.StringUtils;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * ToolTime
 * @description <文件描述: 时间操作工具类>
 * @author xuYingYang
 * @version V1.0
 * @date 2017年10月31日
 * @email xuyingyang_cloud@sina.com
 */
public class ToolTime
{
	/** 时间转化为yyyymmddHHmmss */
	public static final String ALL_TIME = "yyyyMMddHHmmss";
	/** 时间转化为yyyyMMdd */
	public static final String DATE_TIME = "yyyyMMdd";

	/** 时间转化为yyyyMM */
	public static final String YEAR_MONTH = "yyyyMM";

	/** 时间转化为yyyy-MM-dd */
	public static final String DATE_TIME_SPACING = "yyyy-MM-dd";

	/** 时间转化为yyyy-MM-dd HH:mm:ss */
	public static final String ALL_TIME_SPACING = "yyyy-MM-dd HH:mm:ss";

	/** 时间转化为yyyy/MM/dd */
	public static final String DATE_TIME_SLASH = "yyyy/MM/dd";

	private static ThreadLocal<SimpleDateFormat> dateFrt = new ThreadLocal<SimpleDateFormat>();

	/**
	 * 返回当前系统时间
	 * @description <描述：返回的时间格式为yyyyMMddHHmmss>
	 * @return String 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static String getNowStringByAllTime()
	{
		return getStringByAllTimeSpacing( new Date(), ALL_TIME );
	}

	/**
	 * 返回当前系统时间
	 * @description <描述:时间戳>
	 * @return Timestamp 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2018年12月4日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static Timestamp getTimestamp()
	{
		return new Timestamp( getNowDate().getTime() );
	}

	/**
	 * 返回当前系统时间
	 * @description <描述：>
	 * @return Date 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static Date getNowDate()
	{
		return new Date();
	}

	/**
	 * 将date时间转为字符串 yyyyMMddHHmmss
	 * @description <描述：返回的时间格式为c>
	 * @param date 需要转换的时间
	 * @return String 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static String getStringByAllTime( Date date )
	{
		return getStringByAllTimeSpacing( date, ALL_TIME );
	}

	/**
	 * 将时间字符串yyyyMMddHHmmss转换为时间date
	 * @description <描述>
	 * @param dateStr 需要转换的时间字符串
	 * @return date 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @throws ParseException
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static Date getDateByAllTime( String dateStr ) throws ParseException
	{
		return getDateByAllTimeSpacing( dateStr, ALL_TIME );
	}

	/**
	 * 获取系统当前时间的年份和月份
	 * @throws ParseException
	 * @return String
	 * @author xuYingYang
	 * @version V1.0
	 * @date Jul 17, 2019
	 * @email xuyingyang_cloud@outlook.com
	 */
	public static String getYearAndMoush() throws ParseException
	{
		return getStringByAllTimeSpacing( getNowDate(), YEAR_MONTH );
	}

	/**
	 * 返回当前系统时间
	 * @description <描述：返回的时间格式为yyyy-MM-dd HH:mm:ss>
	 * @return String 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static String getNowStringByAllTimeSpacing()
	{
		return getStringByAllTimeSpacing( new Date(), ALL_TIME_SPACING );
	}

	/**
	 * 将date时间转为字符串 yyyy-MM-dd HH:mm:ss
	 * @description <描述：返回的时间格式为c>
	 * @param date 需要转换的时间
	 * @return String 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static String getStringByAllTimeSpacing( Date date )
	{
		return getStringByAllTimeSpacing( date, ALL_TIME_SPACING );
	}

	/**
	 * 将时间字符串 yyyy-MM-dd HH:mm:ss 转换为date
	 * @description <描述：返回的时间格式为c>
	 * @param dateStr 需要转换的时间字符串
	 * @return Date 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @throws ParseException
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static Date getDateByAllTimeSpacing( String dateStr ) throws ParseException
	{
		return getDateByAllTimeSpacing( dateStr, ALL_TIME_SPACING );
	}

	/**
	* @Desc   将date时间转为字符串 yyyy/MM/dd
	* @Author Mr.dong
	* @Date   2021/3/31 15:40
	*/
	public static String getStringBySlash( Date date )
	{
		return getStringByAllTimeSpacing( date, DATE_TIME_SLASH );
	}

	/**
	 * 将date时间转换为指定格式字符串
	 * @description <描述>
	 * @param date 需要转换的时间
	 * @param sdf 转换的格式，如：yyyyMMdd
	 * @return String 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static String getStringByAllTimeSpacing( Date date, String sdf )
	{
        if (null == date) {
            return null;
        }
		return getSdf( sdf ).format( date );
	}

	/**
	 * 将指定格式的时间字符串转换为date
	 * @description <描述>
	 * @param dateStr 需要转换的时间字符串
	 * @param sdf 时间字符串的格式，如：yyyyMMdd
	 * @return Date 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @throws ParseException
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	public static Date getDateByAllTimeSpacing( String dateStr, String sdf ) throws ParseException
	{
		return getSdf( sdf ).parse( dateStr );
	}

	/**
	 * 获取SimpleDateFormat对象
	 * @description <描述： 避免高并发情况下的时间错乱>
	 * @param sdf
	 * @return SimpleDateFormat 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2017年10月31日
	 * @email xuyingyang_cloud@sina.com
	 */
	private static SimpleDateFormat getSdf( String sdf )
	{
		if (null == dateFrt.get() || !dateFrt.get().toPattern().equals( sdf ))
		{
			dateFrt.set( new SimpleDateFormat( sdf ) );
		}
		return dateFrt.get();
	}

	/**
	 * 根据时间格式字符串获取自定义时间字符串
	 * @param formatStr 格式化类型
	 * @param field 日历类型
	 * @param offset 偏移量
	 * @author caocy
	 * @version V1.0
	 * @date 2017年11月19日
	 * @return String 时间字符串
	 */
	public static String format( String formatStr, int field, int offset )
	{
		return format( new Date(), formatStr, field, offset );
	}

	/**
	 * 将日期类型转成自定义时间格式字符串
	 * @param dateTime 传入的时间
	 * @param formatStr 格式化类型 如:
	 *            Calendar.YEAR,Calendar.MONTH,Calendar.DATE,Calendar.HOUR_OF_DAY,Calendar.MINUTE,Calendar.SECOND
	 * @param field 日历类型
	 * @param offset 偏移量
	 * @author caocy
	 * @version V1.0
	 * @date 2017年11月19日
	 * @return String 时间字符串
	 */
	public static String format( Date dateTime, String formatStr, int field, int offset )
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime( dateTime );
		if (field != -1)
		{
			cal.add( field, offset );
		}
		SimpleDateFormat dateFormat = getSdf( formatStr );
		return dateFormat.format( cal.getTime() );
	}

	/**
	 * 根据传入的年月日时分秒，指定时间
	 * @param dateTime 传入的时间
	 * @param year 设置的年
	 * @param month 设置的月
	 * @param day 设置的天
	 * @param hour 设置的时
	 * @param minute 设置的分
	 * @param second 设置的秒
	 * @author caocy
	 * @version V1.0
	 * @date 2017年11月19日
	 * @return 设置后的时间
	 */
	public static Date specifyTime( Date dateTime, int year, int month, int day, int hour, int minute, int second )
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime( dateTime );
		if (year != -1)
		{
			cal.set( Calendar.YEAR, year );
		}
		if (month != -1)
		{
			cal.set( Calendar.MONTH, month );
		}
		if (day != -1)
		{
			cal.set( Calendar.DATE, day );
		}
		if (hour != -1)
		{
			cal.set( Calendar.HOUR_OF_DAY, hour );
		}
		if (minute != -1)
		{
			cal.set( Calendar.MINUTE, minute );
		}
		if (second != -1)
		{
			cal.set( Calendar.SECOND, second );
		}
		return cal.getTime();
	}

	/**
	 * 返回两个yyyyMMddHHmmss格式字符串日期相差的天数
	 * @param startDate 开始时间
	 * @param endDate 结束时间
	 * @author caocy
	 * @version V1.0
	 * @date 2017年12月1日
	 * @return
	 */
	public static long getDistDates( String startDate, String endDate ) throws ParseException
	{
		long totalDate = 0;
		Calendar calendar = Calendar.getInstance();
		calendar.setTime( getDateByAllTime( startDate ) );
		long timestart = calendar.getTimeInMillis();
		calendar.setTime( getDateByAllTime( endDate ) );
		long timeend = calendar.getTimeInMillis();
		totalDate = Math.abs( ( timeend - timestart ) ) / ( 1000 * 60 * 60 * 24 );
		return totalDate;
	}

	/**
	 * 获得当前日期与本周日相差的天数
	 * @author caocy
	 * @version V1.0
	 * @date 2017年1月2日
	 * @return
	 */
	private static int getMondayPlus()
	{
		Calendar cd = Calendar.getInstance();
		// 获得今天是一周的第几天，星期日是第一天，星期二是第二天......
		// 因为按中国礼拜一作为第一天所以这里减1
		int dayOfWeek = cd.get( Calendar.DAY_OF_WEEK ) - 1;
		if (dayOfWeek == 1)
		{
			return 0;
		}
		else
		{
			return 1 - dayOfWeek;
		}
	}

	/**
	 * 获得本周一的日期
	 * @author caocy
	 * @version V1.0
	 * @date 2017年1月2日
	 * @return
	 */
	public static String getMondayOFWeek()
	{
		int mondayPlus = getMondayPlus();
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add( Calendar.DATE, mondayPlus );
		Date monday = currentDate.getTime();
		DateFormat df = DateFormat.getDateInstance();
		String preMonday = df.format( monday );
		return preMonday;
	}

	public static Date getDateByString_spacing( String data ) throws ParseException
	{
		return getDateByAllTimeSpacing( data, DATE_TIME_SPACING );
	}

	/**
	 * 将时间添加235959后缀
	 * @description <描述>
	 * @param time
	 * @return String 返回类型
	 * @author xuYingYang
	 * @version V1.0
	 * @date 2018年8月7日
	 * @email xuyingyang_cloud@sina.com
	 */
	@SuppressWarnings( "deprecation" )
	public static String addLastTime( String time, String sdf )
	{
		try
		{
			Date date = null;
			if (StringUtils.equals( sdf, DATE_TIME_SPACING ))
			{
				date = getDateByString_spacing( time );

			}
			if (date != null)
			{
				date.setHours( 23 );
				date.setMinutes( 59 );
				date.setSeconds( 59 );
				return getStringByAllTime( date );
			}
		}
		catch ( ParseException e )
		{
			e.printStackTrace();
		}

		return time;
	}

	/**
	 * 判断该日期是否是该月的最后一天
	 *
	 * @param date 需要判断的日期
	 * @return
	 */
	public static boolean isLastDayOfMonth( Date date )
	{
		Calendar calendar = Calendar.getInstance();
		calendar.setTime( date );
		return calendar.get( Calendar.DAY_OF_MONTH ) == calendar.getActualMaximum( Calendar.DAY_OF_MONTH );
	}

	/**
	 * @Des 传入月份格式字符串获取月份的第一天00：00：00
	 * @Date 2020/12/2 14:52
	 * @Author wangzhaoyu
	 * @Param [month]
	 * @Return java.util.Date
	 */
	public static Date getMonthBegin(String month) throws Exception {
		if(StringUtils.isEmpty(month)){
			throw new Exception("格式错误");
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		Date monthDate = null;
		try {
			monthDate = sdf.parse(month);
		} catch (ParseException e) {
			throw new Exception("格式错误");
		}
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(monthDate);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND,0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * @Des
	 * @Date 2020/12/2 14:55
	 * @Author wangzhaoyu
	 * @Param [month]
	 * @Return java.util.Date
	 */
	public static Date getMonthEndTime(String month) throws Exception {

		if(StringUtils.isEmpty(month)){
			throw new Exception("格式错误");
		}
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
		Date monthDate = null;
		try {
			monthDate = sdf.parse(month);
		} catch (ParseException e) {
			throw new Exception("格式错误");
		}
		Calendar calEnd = Calendar.getInstance();
		calEnd.setTime(monthDate);
		calEnd.set(Calendar.DAY_OF_MONTH, calEnd.getActualMaximum(Calendar.DAY_OF_MONTH));
		calEnd.set(Calendar.HOUR_OF_DAY, 23);
		calEnd.set(Calendar.MINUTE, 59);
		calEnd.set(Calendar.SECOND, 59);
		calEnd.set(Calendar.MILLISECOND, 999);
		return calEnd.getTime();
	}

	/**
	 * @Des 获取两个日期的月份差
	 * @Date 2020/12/2 16:50
	 * @Author wangzhaoyu
	 * @Param [startTime, endTime]
	 * @Return java.lang.Integer
	 */
	public static Integer getDifMonth(Date startTime,Date endTime) throws Exception {
		if(startTime == null || endTime == null){
			throw new Exception("参数错误");
		}
		Calendar startCal = Calendar.getInstance();
		startCal.setTime(startTime);

		Calendar endCal = Calendar.getInstance();
		endCal.setTime(endTime);
		int result = endCal.get(Calendar.MONTH) - startCal.get(Calendar.MONTH);
		int month = (endCal.get(Calendar.YEAR) - startCal.get(Calendar.YEAR)) * 12;
		return Math.abs(month + result);
	}

	/**
	 * @Des 获取两个日期的天数差
	 * @Date 2020/12/2 16:50
	 * @Author wangzhaoyu
	 * @Param [startTime, endTime]
	 * @Return java.lang.Integer
	 */
	public static Integer getDifDays(Date startTime,Date endTime) throws Exception {
		if(startTime == null || endTime == null){
			throw new Exception("参数错误");
		}
		long time1 = startTime.getTime();
		long time2 = endTime.getTime();
		long difMillions = time2 - time1;
		long l = difMillions / 1000 / 60 / 60 / 24;
		if(difMillions % (1000*60*60*24) == 0){
			return Integer.valueOf(String.valueOf(l));
		}else{
			return Integer.valueOf(String.valueOf(l))+1;
		}
	}
}
